package lanQiaoBei.搜索与图论.二分图;
import java.io.*;
import java.math.*;
import java.util.*;
/*匈牙利算法(求二分图的最大匹配)
*给定一个二分图，其中左半部包含 n1 个点（编号 1∼n1），右半部包含 n2 个点（编号 1∼n2），二分图共包含 m 条边。

数据保证任意一条边的两个端点都不可能在同一部分中。

请你求出二分图的最大匹配数。

二分图的匹配：给定一个二分图 G，在 G 的一个子图 M 中，M 的边集 {E} 中的任意两条边都不依附于同一个顶点，则称 M 是一个匹配。
二分图的最大匹配：所有匹配中包含边数最多的一组匹配被称为二分图的最大匹配，其边数即为最大匹配数。

输入格式
第一行包含三个整数 n1、 n2 和 m。

接下来 m 行，每行包含两个整数 u 和 v，表示左半部点集中的点 u 和右半部点集中的点 v 之间存在一条边。

输出格式
输出一个整数，表示二分图的最大匹配数。

数据范围
1≤n1,n2≤500,
1≤u≤n1,
1≤v≤n2,
1≤m≤105

输入样例：
2 2 4
1 1
1 2
2 1
2 2
输出样例：
2
* */
public class P2 {
       static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
       final static int N=510,M=100010;
       static int h[]=new int[N],e[]=new int[M],ne[]=new int[M],match[]=new int[N],idx,n1,n2,m;
       static boolean st[]=new boolean[N];
       static void add(int a,int b){
              e[idx]=b;ne[idx]=h[a];h[a]=idx++;
       }
       static void scan()throws Exception{
              String[]ss=br.readLine().split(" ");
              n1=Integer.parseInt(ss[0]);n2=Integer.parseInt(ss[1]);m=Integer.parseInt(ss[2]);
              Arrays.fill(h,-1);
              while(m-->0){
                  ss=br.readLine().split(" ");
                  int a=Integer.parseInt(ss[0]),b=Integer.parseInt(ss[1]);
                  add(a,b);
              }
       }
       static boolean find(int x){
              for(int i=h[x];i!=-1;i=ne[i]){
                  int j=e[i];
                  if(!st[j]){
                      st[j]=true;
                      if(match[j]==0||find(match[j])) {
                          match[j] = x;
                          return true;
                      }
                  }
              }
              return false;
       }
       public static void main(String[]args)throws Exception{
              scan();
              int res=0;
              for(int i=1;i<=n1;i++){
                  Arrays.fill(st,false);
                  if(find(i))res++;
              }
              System.out.print(res);
       }
}
